home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 9675 / 9675.xpi / chrome / content / simpletimer-dragndrop.js < prev    next >
Text File  |  2009-11-20  |  11KB  |  249 lines

  1. // Based on code taken from the IE Tab add-on, as well as the template at
  2. // http://kb.mozillazine.org/Dev_:_Extensions_:_Example_Code_:_Adding_Drag_and_Drop_to_Statusbarpanel
  3. // Fixed some bugs, and didn't like how IE Tab displayed hidden panels while dragging (changed).
  4. // Also, some themes do not display the red vertical line while dragging, fiddled with CSS
  5. // but no luck.
  6.  
  7. var SimpleStatObserver = {
  8.     init: function () {
  9.         // Any text you want but should have something to do with the extension name.
  10.         SimpleStatObserver.flavour = "SimpleTimerFla";
  11.  
  12.         // id of the statusbarpanel to drag.
  13.         SimpleStatObserver.statusbarPanel = "simtim-statpanelTimer";
  14.  
  15.         // id of statusbar.
  16.         SimpleStatObserver.statbar = "status-bar";
  17.  
  18.         try {
  19.             SimpleStatObserver.prefs = Components.classes["@mozilla.org/preferences-service;1"].
  20.                     getService(Components.interfaces.nsIPrefService).
  21.                     getBranch("extensions.simpletimer@grbradt.org.");
  22.  
  23.             // Checks whether the preference has been changed from the default value (empty string)
  24.             // and inserts our panel before the element referenced in preference.
  25.             // Default position is last.
  26.             if ( SimpleStatObserver.prefs.prefHasUserValue("insertBefore") &&
  27.                  SimpleStatObserver.prefs.getCharPref("insertBefore") !== "last" ) {
  28.                 document.getElementById(SimpleStatObserver.statbar).
  29.                         insertBefore(document.getElementById(SimpleStatObserver.statusbarPanel),
  30.                                      document.getElementById(SimpleStatObserver.prefs.getCharPref("insertBefore")));
  31.             }
  32.             else {
  33.                 document.getElementById(SimpleStatObserver.statbar).
  34.                         appendChild(document.getElementById(SimpleStatObserver.statusbarPanel));
  35.             }
  36.         }
  37.         catch(e) {
  38.             document.getElementById(SimpleStatObserver.statbar).
  39.                         appendChild(document.getElementById(SimpleStatObserver.statusbarPanel));
  40.         }
  41.  
  42.         // Starting with FF 3.6, dragdrop event replaced by drop event.
  43.         // Both events were available in FF 3.5 (first implementation of HTML5 dnd).
  44.         SimpleStatObserver.dropEvent = "drop";
  45.  
  46.         try {
  47.             var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
  48.                     getService(Components.interfaces.nsIXULAppInfo);
  49.             var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"].
  50.                     getService(Components.interfaces.nsIVersionComparator);
  51.  
  52.             if ( appInfo.name === "Firefox" ) {
  53.                 if ( versionChecker.compare(appInfo.version, "3.6a1" ) < 0 ) {
  54.                     SimpleStatObserver.dropEvent = "dragdrop";
  55.                 }
  56.             }
  57.         }
  58.         catch(e) {
  59.         }
  60.     },
  61.  
  62.     // The type of data being dragged is stored as a set of flavours.
  63.     // Often, a dragged object will be available in a number of flavours.
  64.     // That way, a drop target can accept the flavour it finds most suitable.
  65.     getSupportedFlavours: function () {
  66.         var flavours = new FlavourSet();
  67.         flavours.appendFlavour(SimpleStatObserver.flavour); // text/unicode
  68.         return flavours;
  69.     },
  70.  
  71.     // Begin drag, set the transfer data and attach drag event listeners
  72.     // to each statusbar panel.
  73.     onDragStart: function (evt, transferData, action) {
  74.         var elme = evt.target;
  75.  
  76.         // See if target element was child label or image, eg.
  77.         while ( elme != document.getElementById(SimpleStatObserver.statusbarPanel) ) {
  78.             elme = elme.parentNode;
  79.         }
  80.  
  81.         // Data being transferred is our panel id, in text/unicode format
  82.         var txt = elme.getAttribute("id");
  83.         transferData.data = new TransferData();
  84.         transferData.data.addDataForFlavour(SimpleStatObserver.flavour, txt);
  85.         var statusPanel = document.getElementById(SimpleStatObserver.statusbarPanel);
  86.         var statusbar = document.getElementById(SimpleStatObserver.statbar);
  87.         var child = statusbar.firstChild;
  88.         var x = 0;
  89.  
  90.         // Check if each panel has id, add listeners to each panel.
  91.         // Keep in mind that some children of statusbar may not be statusbarpanels,
  92.         // eg deck, popupset etc.
  93.         while ( child ) {
  94.             if ( child != statusPanel ) {
  95.                 if ( !child.id ) {
  96.                     // If you insert before a no-id, positioning is lost
  97.                     // on browser restart. id doesn't persist.
  98.                     var newId = "statusbarpanel-noID" + x;
  99.                     while ( document.getElementById(newId) ) {
  100.                         newId += "x" + x;
  101.                     }
  102.                     child.id = newId;
  103.                     child.setAttribute("persist",
  104.                                        new String("id" + (child.persist ? " " + child.persist : "")));
  105.                     x++;
  106.                 }
  107.  
  108.                 child.addEventListener("dragenter", function(event) { nsDragAndDrop.dragEnter(event, SimpleStatObserver); }, false);
  109.                 child.addEventListener("dragover", function(event) { nsDragAndDrop.dragOver(event, SimpleStatObserver); }, false);
  110.                 child.addEventListener("dragexit", function(event) { nsDragAndDrop.dragExit(event, SimpleStatObserver); }, false);
  111.                 child.addEventListener(SimpleStatObserver.dropEvent, function(event) { nsDragAndDrop.drop(event, SimpleStatObserver); }, false);
  112.             }
  113.  
  114.             child = child.nextSibling;
  115.         }
  116.  
  117.         window.addEventListener("dragend", function(event) { SimpleStatObserver.dragEnd(); }, true);
  118.     },
  119.  
  120.     // Entering a panel.
  121.     onDragEnter: function (evt, flavour, session) {
  122.         var elm = evt.target;
  123.  
  124.         while ( elm && elm.nodeName.toLowerCase() != "statusbarpanel" ) {
  125.             elm = elm.parentNode;
  126.         }
  127.     },
  128.  
  129.     // Moving over a panel.
  130.     onDragOver: function (evt, flavour, session) {
  131.         var elm = evt.target;
  132.  
  133.         while ( elm.nodeName.toLowerCase() != "statusbarpanel" &&
  134.                 elm.parentNode.nodeName.toLowerCase() != "statusbar" ) {
  135.             elm = elm.parentNode;
  136.         }
  137.  
  138.         // This will display a little vertical red line where the drop will occur.
  139.         // Calculate mid-point of panel we are moving over.
  140.         var midPointCoord = elm.boxObject.x + ( elm.boxObject.width / 2 );
  141.  
  142.         if ( evt.clientX < midPointCoord ) {
  143.             elm.setAttribute("simtimstatdrag", "left");
  144.         }
  145.         else {
  146.             elm.setAttribute("simtimstatdrag", "right");
  147.         }
  148.     },
  149.  
  150.     // Leaving a panel. Remove the vertical red line.
  151.     onDragExit: function (evt, session) {
  152.         var elm = evt.target;
  153.  
  154.         while ( elm.nodeName.toLowerCase() != "statusbarpanel" &&
  155.                 elm.parentNode.nodeName.toLowerCase() != "statusbar" ) {
  156.            elm = elm.parentNode;
  157.         }
  158.  
  159.         elm.removeAttribute("simtimstatdrag");
  160.     },
  161.  
  162.     // Dropped.
  163.     onDrop: function (evt, dropdata, session) {
  164.         if ( dropdata.data != "" ) {
  165.             var prefs = Components.classes["@mozilla.org/preferences-service;1"].
  166.                     getService(Components.interfaces.nsIPrefService).
  167.                     getBranch("extensions.simpletimer@grbradt.org.");
  168.             var elm = evt.target;
  169.  
  170.             // May have dropped on image or label.
  171.             while ( elm.parentNode.nodeName.toLowerCase() != "statusbar" ) {
  172.                 elm = elm.parentNode;
  173.             }
  174.  
  175.             // Calculate mid-point again.
  176.             var midPointCoord = elm.boxObject.x + ( elm.boxObject.width / 2 );
  177.  
  178.             // elem is the dropped panel.
  179.             var elem = document.getElementById(dropdata.data);
  180.             var parent = elem.parentNode;
  181.  
  182.             if ( evt.clientX > midPointCoord ) {
  183.                 // Dropped on right side of mid-point.
  184.                 elm = elm.nextSibling;
  185.                 if ( elm == elem ) {
  186.                     elm = elm.nextSibling;
  187.                 }
  188.             }
  189.  
  190.             // Don't insert before non-panel/deck statusbar children eg popupset.
  191.             while ( elm && ( ( elm.nodeName.toLowerCase() != "statusbarpanel" &&
  192.                     elm.nodeName.toLowerCase() != "deck" ) ||
  193.                     elm == elem ) ) {
  194.                 elm = elm.nextSibling;
  195.             }
  196.  
  197.             if ( elm ) {
  198.                 try {
  199.                     parent.insertBefore(elem, elm);
  200.                 }
  201.                 catch(e) {
  202.                 }
  203.  
  204.                 elem.setAttribute("insertbefore", "" + elm.getAttribute("id"));
  205.                 prefs.setCharPref("insertBefore", elm.getAttribute("id") + "");
  206.             }
  207.             else {
  208.                 parent.appendChild(elem);
  209.                 elem.setAttribute("insertbefore", "last");
  210.                 prefs.setCharPref("insertBefore", "last");
  211.             }
  212.         }
  213.     },
  214.  
  215.     // Clean up.
  216.     dragEnd: function () {
  217.         var statusbar = document.getElementById(SimpleStatObserver.statbar);
  218.         var statusbarPanel = document.getElementById(SimpleStatObserver.statusbarPanel);
  219.  
  220.         // Remove the event handlers
  221.         var child = statusbar.firstChild;
  222.  
  223.         while (child) {
  224.             if ( child != statusbarPanel ) {
  225.                 child.removeAttribute("simtimstatdrag");
  226.                 child.removeEventListener("dragenter", function(event) { nsDragAndDrop.dragEnter(event, SimpleStatObserver); }, false);
  227.                 child.removeEventListener("dragover", function(event) { nsDragAndDrop.dragOver(event, SimpleStatObserver); }, false);
  228.                 child.removeEventListener("dragexit", function(event) { nsDragAndDrop.dragExit(event, SimpleStatObserver); }, false);
  229.                 child.removeEventListener(SimpleStatObserver.dropEvent, function(event) { nsDragAndDrop.drop(event, SimpleStatObserver); }, false);
  230.             }
  231.  
  232.           child = child.nextSibling;
  233.         }
  234.  
  235.         window.removeEventListener("dragend", function(event) { nsDragAndDrop.dragExit(event, SimpleStatObserver); }, true);
  236.     },
  237.  
  238.     goodbye: function() {
  239.         window.removeEventListener('load', SimpleStatObserver.init, false);
  240.         window.removeEventListener('unload', SimpleStatObserver.goodbye, false);
  241.     },
  242.  
  243.     debug: function (aMsg) {
  244.         setTimeout(function() { throw new Error("[debug] " + aMsg); }, 0);
  245.     }
  246. };
  247. window.addEventListener('load', SimpleStatObserver.init, false);
  248. window.addEventListener('unload', SimpleStatObserver.goodbye, false);
  249.